require "#{SRC}/string"
require "#{SRC}/exception"

class Book

	public

		def initialize
			$gbook = GladeXML.new("#{GLADE}/book.glade") {|handler| method(handler)}
			$gbook["flagview"].clear
			$gbook["flagview"].model = flagview_model
			renderer = Gtk::CellRendererPixbuf.new
			$gbook["flagview"].pack_start(renderer, false)
			$gbook["flagview"].add_attribute(renderer, "pixbuf", 0)
			renderer = Gtk::CellRendererText.new
			$gbook["flagview"].pack_start(renderer, true)
			$gbook["flagview"].add_attribute(renderer, "text", 1)
		end

		def show(cod_book = nil)
			@cod_book = cod_book

			completion, model = author_completion_model
			$gbook["author"].completion = completion
			$gbook["author_cb"].model = model
			$gbook["author_cb"].text_column = 0

			completion, model = publisher_completion_model
			$gbook["publisher"].completion = completion
			$gbook["publisher_cb"].model = model
			$gbook["publisher_cb"].text_column = 0

			$gbook["genre_cb"].clear
			$gbook["genre_cb"].model = genre_model
			renderer = Gtk::CellRendererText.new
			$gbook["genre_cb"].pack_start(renderer, true)
			$gbook["genre_cb"].add_attribute(renderer, "text", 1)

			$gbook["language_cb"].clear
			$gbook["language_cb"].model = language_model
			renderer = Gtk::CellRendererText.new
			$gbook["language_cb"].pack_start(renderer, true)
			$gbook["language_cb"].add_attribute(renderer, "text", 2)
			renderer = Gtk::CellRendererPixbuf.new
			$gbook["language_cb"].pack_start(renderer, false)
			$gbook["language_cb"].add_attribute(renderer, "pixbuf", 1)

			clear_screen

			if cod_book == nil
				$gbook["borrowed"].sensitive = false
				$gbook["read"].sensitive = false
			else
				$db.results_as_hash = true
				rc = $db.get_first_row("SELECT * FROM book WHERE cod_book = #{cod_book}")
				$db.results_as_hash = false
				$gbook["isbn"].text = rc["isbn"]
				$gbook["name"].text = rc["name"]
				$gbook["original_title"].text = rc["original_title"]
				$gbook["year"].text = rc["year"]
				$gbook["pages"].text = rc["pages"]
				$gbook["author"].text = $db.get_first_value("SELECT author FROM author WHERE cod_author = #{rc["cod_author"]}")
				$gbook["publisher"].text = $db.get_first_value("SELECT publisher FROM publisher WHERE cod_publisher = #{rc["cod_publisher"]}")

				store = $gbook["language_cb"].model
				store.each do | model, path, iter |
					$gbook["language_cb"].active_iter = iter if iter[0] == rc["cod_language"].to_i
				end

				cod_genre = $db.get_first_value("SELECT father FROM genre WHERE cod_genre = #{rc["cod_genre"]}").to_i
				tmp = cod_genre
				if cod_genre == 0
					cod_genre = rc["cod_genre"].to_i
				end
				store = $gbook["genre_cb"].model
				store.each do | model, path, iter |
					$gbook["genre_cb"].active_iter = iter if iter[0] == cod_genre
				end

				if tmp != 0
					$gbook["subgenre"].text = $db.get_first_value("SELECT genre FROM genre WHERE cod_genre = #{rc["cod_genre"]}")
				end

				if File.readable?("#{BOOKIMGS}/#{cod_book}.jpg")
					$gbook["image"].pixbuf = Gdk::Pixbuf.new("#{BOOKIMGS}/#{cod_book}.jpg")
				end

				$gbook["borrowed"].sensitive = true
				$gbook["read"].sensitive = true
			end

			$gbook["book_window"].show
			$gbook["isbn"].set_focus(true)

		end

	private

		def clear_screen
			["isbn", "name", "author", "publisher", "subgenre", "original_title", "year", "pages"].each do |fd|
				$gbook[fd].text = ""
			end

			# Set default language
			default_language = $db.get_first_value("SELECT default_language FROM config").to_i
			store = $gbook["language_cb"].model
			store.each do | model, path, iter |
				$gbook["language_cb"].active_iter = iter if iter[0] == default_language
			end

#			$gbook["genre_cb"].active = -1
			$gbook["image"].pixbuf = nil
		end

		def author_completion_model
			c = Gtk::EntryCompletion.new
			st = Gtk::ListStore.new(String)
			$db.execute("SELECT author FROM author WHERE cod_author != 0 ORDER BY author") do |r|
				iter = st.append
				iter[0] = r[0]
			end
			c.model = st
			c.text_column = 0
			return c, st
		end

		def publisher_completion_model
			c = Gtk::EntryCompletion.new
			st = Gtk::ListStore.new(String)
			$db.execute("SELECT publisher FROM publisher WHERE cod_publisher != 0 ORDER BY publisher") do |r|
				iter = st.append
				iter[0] = r[0]
			end
			c.model = st
			c.text_column = 0
			return c, st
		end

		def genre_model
			st = Gtk::ListStore.new(Integer, String)
			$db.execute("SELECT cod_genre, genre FROM genre WHERE (father = '' OR father IS NULL) AND cod_genre != 0 ORDER BY genre") do |r|
				iter = st.append
				iter[0] = r[0].to_i
				iter[1] = r[1]
			end
			return st
		end

		def language_model
			st = Gtk::ListStore.new(Integer, Gdk::Pixbuf, String)
			$db.execute("SELECT cod_language, flag, language 
                        FROM language 
					   WHERE cod_language != 0
                    ORDER BY language") do |r|
				iter = st.append
				iter[0] = r[0].to_i
				if r[1] != nil
					iter[1] = Gdk::Pixbuf.new("#{IMG}/#{r[1]}.gif")
				end
				iter[2] = r[2]
			end
			return st
		end

		def flagview_model
			st = Gtk::ListStore.new(Gdk::Pixbuf, String)
			Dir["#{IMG}/*.gif"].each do |file|
				iter = st.append
				iter[0] = Gdk::Pixbuf.new(file)
				iter[1] = file.sub('.gif', '').sub("#{IMG}/", '')
			end
			return st
		end

		def subgenre_completion_model
			# Get genre
			begin
				cod_genre = $gbook["genre_cb"].active_iter[0]
			rescue
				cod_genre = 0
			end
			return nil, nil if cod_genre == 0 or cod_genre == nil
			c = Gtk::EntryCompletion.new
			st = Gtk::ListStore.new(String)
			$db.execute("SELECT genre FROM genre WHERE father = #{cod_genre} AND cod_genre != 0 ORDER BY genre") do |r|
				iter = st.append
				iter[0] = r[0]
			end
			c.model = st
			c.text_column = 0
			return c, st
		end

		def default_language
			1
		end

	# Events

		def on_ok
			save
			$list.populate_list($list.list_store)
		end

		def delete_book
			$gbook["book_window"].hide_on_delete
		end

		def save

			if $gbook["name"].text.strip == ""
				d = Gtk::MessageDialog.new($gbook["book_window"],
									   Gtk::Dialog::MODAL,
									   Gtk::MessageDialog::WARNING,
									   Gtk::MessageDialog::BUTTONS_OK,
									   _("A book name must be informed."))
				d.run
				d.destroy
				return
			end

			isbn = $gbook["isbn"].text.strip.escape
			name = $gbook["name"].text.strip.escape
			original_title = $gbook["original_title"].text.strip.escape
			year = $gbook["year"].text.to_i
			year = 'NULL' if year == 0
			pages = $gbook["pages"].text.to_i
			pages = 'NULL' if pages == 0
			begin
				cod_language = $gbook["language_cb"].active_iter[0]
			rescue
				cod_language = 0
			end
			begin
				cod_genre = $gbook["genre_cb"].active_iter[0]
			rescue
				cod_genre = 0
			end

			# Check for new data
			if $gbook["author"].text.strip != ""
				if not $db.get_first_value("SELECT count(*) 
    	                               FROM author 
        	                          WHERE author LIKE '#{$gbook["author"].text}'").to_i > 0
					begin
						$db.execute("INSERT INTO author (author) VALUES ('#{$gbook["author"].text.escape}')")
					rescue SQLite3::SQLException => e
						Error.db_error(e)
						return
					end
				end
			end
			if $gbook["publisher"].text.strip != ""
				if not $db.get_first_value("SELECT count(*) 
    	                               FROM publisher 
        	                          WHERE publisher LIKE '#{$gbook["publisher"].text}'").to_i > 0
					begin
						$db.execute("INSERT INTO publisher (publisher) VALUES ('#{$gbook["publisher"].text.escape}')")
					rescue SQLite3::SQLException => e
						Error.db_error(e)
					end
				end
			end
			if cod_genre != 0 and $gbook["subgenre"].text.strip != ""
				if not $db.get_first_value("SELECT count(*) 
                                   FROM genre
                                  WHERE genre LIKE '#{$gbook["subgenre"].text.strip.escape}'
												AND father = #{cod_genre}").to_i > 0
					begin
						$db.execute("INSERT INTO genre (genre, father) VALUES (?, ?)", $gbook["subgenre"].text.strip.escape, cod_genre)
					rescue SQLite3::SQLException => e
						Error.db_error(e)
					end
				end
			end

			# Author
			cod_author = $db.get_first_value("SELECT cod_author
                                            FROM author 
                                           WHERE author LIKE '#{$gbook["author"].text}'").to_i

			# Publisher
			cod_publisher = $db.get_first_value("SELECT cod_publisher
                                                   FROM publisher 
                                                  WHERE publisher LIKE '#{$gbook["publisher"].text}'").to_i

			# Subgenre
			cod_subgenre = $db.get_first_value("SELECT cod_genre
                                                  FROM genre 
                                                 WHERE genre LIKE '#{$gbook["subgenre"].text}'
                                                   AND father = #{cod_genre}").to_i
			cod_subgenre = cod_genre if cod_subgenre == 0

			# Add book
			if @cod_book == nil
				begin
					$db.execute("INSERT INTO book
							             ( cod_genre, cod_author, cod_language
							             , cod_publisher, isbn, name, pages, year
										 , original_title )
							      VALUES ( #{cod_subgenre}, #{cod_author}
							             , #{cod_language}, #{cod_publisher}
							             , '#{isbn}', '#{name}', #{pages}, #{year}
									     , '#{original_title}' )")
				rescue SQLite3::SQLException => e
					Error.db_error(e)
				end
				cod_book = $db.get_first_value("SELECT max(cod_book) FROM book");
			else
				begin
					$db.execute("UPDATE book
							    SET cod_genre = #{cod_subgenre}
							      , cod_author = #{cod_author}
							      , cod_language = #{cod_language}
							      , cod_publisher = #{cod_publisher}
							      , isbn = '#{isbn}'
							      , name = '#{name}'
							      , pages = #{pages}
							      , year = #{year}
								  , original_title = '#{original_title}'
							  WHERE cod_book = #{@cod_book}")
				rescue SQLite3::SQLException => e
					Error.db_error(e)
				end
				cod_book = @cod_book
			end

			# Save image
			if $gbook["image"].pixbuf != nil
				pixbuf = $gbook["image"].pixbuf.save("#{BOOKIMGS}/#{cod_book}.jpg", "jpeg")
				size_x = pixbuf.width
				size_y = pixbuf.height
				ratio_x = 27.0 / size_x
				ratio_y = 36.0 / size_y
				if ratio_x > ratio_y
					ratio = ratio_x
				else
					ratio = ratio_y
				end
				pixbuf = pixbuf.scale(size_x * ratio, size_y * ratio, Gdk::Pixbuf::INTERP_HYPER)
				pixbuf.save("#{BOOKIMGS}/#{cod_book}s.jpg", "jpeg")
			end

			# Cleanup database
			$list.cleanup_database

			# Close screen
			if $gbook["keep_open"].active?
				show
			else
				$gbook["book_window"].hide
			end	

		end

		def genre_changed
			$gbook["subgenre"].text = ""
			completion, model = subgenre_completion_model
			if completion != nil
				$gbook["subgenre"].completion = completion
				$gbook["subgenre_cb"].model = model
				$gbook["subgenre_cb"].text_column = 0
			end
		end

		def file_chosen(file)
			pixbuf = Gdk::Pixbuf.new(file)
			
			# Resize
			size_x = pixbuf.width
			size_y = pixbuf.height
			ratio_x = 150.0 / size_x
			ratio_y = 200.0 / size_y
			if ratio_x < ratio_y
				ratio = ratio_x
			else
				ratio = ratio_y
			end

			pixbuf = pixbuf.scale(size_x * ratio, size_y * ratio, Gdk::Pixbuf::INTERP_HYPER)

			$gbook["image"].pixbuf = pixbuf
		end

		def search_image
			d= Gtk::FileChooserDialog.new(_("Open Cover Image"),
										  $gbook["book_window"],
										  Gtk::FileChooser::ACTION_OPEN,
										  nil,
										  [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
										  [Gtk::Stock::OPEN, Gtk::Dialog::RESPONSE_ACCEPT])
			if d.run == Gtk::Dialog::RESPONSE_ACCEPT
				file_chosen(d.filename)
			end
			d.destroy
		end

		def new_genre_clicked
			$gbook["new_genre"].text = ""
			$gbook["new_genre_dialog"].run
		end

		def new_language_clicked
			$gbook["new_language"].text = ""
			$gbook["new_language_dialog"].run
		end

	# New genre events

		def new_genre_ok
			new_genre = $gbook["new_genre"].text.strip
			if new_genre != ""
				if $db.get_first_value("SELECT count(*) FROM genre WHERE genre LIKE '#{new_genre}'").to_i == 0
					begin
						$db.execute("INSERT INTO genre ( genre ) VALUES ( '#{new_genre}' )")
					rescue SQLite3::SQLException => e
						Error.db_error(e)
					end
				end
			end

			# Requery genre
			$gbook["genre_cb"].model = genre_model
			$gbook["genre_cb"].model.each do | model, path, iter |
				$gbook["genre_cb"].active_iter = iter if iter[1] == new_genre
			end

			$gbook["new_genre_dialog"].hide
		end

		def new_genre_cancel
			$gbook["new_genre_dialog"].hide
		end

		def new_genre_close
			$gbook["new_genre_dialog"].hide_on_delete
		end

	# New genre events

		def new_language_ok
			if $gbook['flagview'].selected_items == []
				d = Gtk::MessageDialog.new($gbook["new_language_dialog"],
									   Gtk::Dialog::MODAL,
									   Gtk::MessageDialog::ERROR,
									   Gtk::MessageDialog::BUTTONS_OK,
									   _("No flag selected."))
				d.secondary_text = _("A flag must be selected in order to create a new language.")
				d.run
				d.destroy
				return	
			end

			new_language = $gbook["new_language"].text.strip
			if new_language != ""
				if $db.get_first_value("SELECT count(*) FROM language WHERE language LIKE '#{new_language}'").to_i == 0
					begin
						$db.execute("INSERT INTO language ( flag, language ) VALUES ( '#{$gbook['flagview'].model.get_iter($gbook['flagview'].selected_items[0])[1]}', '#{new_language}' )")
					rescue SQLite3::SQLException => e
						Error.db_error(e)
					end
				end
			end

			# Requery genre
			$gbook["language_cb"].model = language_model
			$gbook["language_cb"].model.each do | model, path, iter |
				$gbook["language_cb"].active_iter = iter if iter[2] == new_language
			end

			$gbook["new_language_dialog"].hide
		end

		def new_language_cancel
			$gbook["new_language_dialog"].hide
		end

		def new_language_close
			$gbook["new_language_dialog"].hide_on_delete
		end

end
